#include "base/channel.h"
#include "base/eventloop.h"
#include "base/timer.h"
#include "base/timeeverymap.h"
#include "base/log.h"

#include "base/timeevery.h"
namespace net_tools::base
{
  Timeevery::Timeevery(func func, timeval begin_time, timeval time, int count, net_tools::Eventloop *eventloop, Timeeverymap *timeeverymap, const std::string &name)
      : timer_(new Timer()),
        timerfd_(timer_->Gettimefd()),
        func_(std::move(func)),
        begin_time_(begin_time),
        time_(time),
        next_time_(begin_time),
        count_(count),
        eventloop_(eventloop),
        timeeverymap_(timeeverymap),
        time_job_name_(std::move(name)),
        is_takeplace_other_(false)
  {
    if (timeeverymap_->Add_timejob(time_job_name_, this))
    {
      is_takeplace_other_ = true;
    }
    NT_LOG_TRACE << "Timejobname: " << time_job_name_ << " CREAT" << NT_LOG_ENDL;
    Set_time();
  }
  Timeevery::~Timeevery()
  {
    delete timer_;
  };
  void Timeevery::Time_out()
  {
    if (count_ > 0)
    {
      func_();
      --count_;
      next_time_.tv_sec = next_time_.tv_sec + time_.tv_sec;
      next_time_.tv_usec = next_time_.tv_usec + time_.tv_usec;
      if (next_time_.tv_usec >= 1000000)
      {
        next_time_.tv_usec -= 1000000;
        ++next_time_.tv_sec;
      }
      Set_time();
    }
    else if (count_ == -1)
    {
      func_();
      next_time_.tv_sec = next_time_.tv_sec + time_.tv_sec;
      next_time_.tv_usec = next_time_.tv_usec + time_.tv_usec;
      if (next_time_.tv_usec >= 1000000)
      {
        next_time_.tv_usec -= 1000000;
        ++next_time_.tv_sec;
      }
      Set_time();
    }
    else
    {
      timeeverymap_->Del_timejob(time_job_name_);
    }
  };
  void Timeevery::Clean_timeevery()
  {
    channel_->Del_to_epoll();
    eventloop_->Free_channel_right_now(channel_);
    delete this;
  };
  void Timeevery::Set_time()
  {
    timeval now_time, set;
    gettimeofday(&now_time, NULL);
    set.tv_usec = next_time_.tv_usec - now_time.tv_usec;
    set.tv_sec = next_time_.tv_sec - now_time.tv_sec;
    if (set.tv_usec < 0)
    {
      set.tv_usec += 1000000;
      --set.tv_sec;
    }
    if (set.tv_sec < 0)
    {
      set.tv_usec = 0;
      set.tv_sec = 0;
    }
    timer_->Settime(set);
  };

} // namespace net_tools::base